/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace FaceCat {
    /// <summary>
    /// 视图事件
    /// </summary>
    /// <param name="sender">发送者</param>
    /// <param name="cancel">是否退出</param>
    public interface FCWindowClosingEventCallBack
    {
        /// <summary>
        /// 调用事件
        /// </summary>
        /// <param name="eventName"></param>
        /// <param name="sender"></param>
        /// <param name="cancel"></param>
        /// <param name="invoke"></param>
        void callWindowClosingEvent(String eventName, Object sender, ref bool cancel, Object invoke);
    }

    /// <summary>
    /// 窗体视图
    /// </summary>
    public class FCWindow : FCView {
        /// <summary>
        /// 创建窗体视图
        /// </summary>
        public FCWindow() {
            setAllowDrag(true);
            setIsWindow(true);
            setVisible(false);
        }

        /// <summary>
        /// 上次坐标
        /// </summary>
        public FCPoint m_oldLocation = new FCPoint();

        /// <summary>
        /// 调整尺寸的点
        /// </summary>
        public int m_resizePoint = -1;

        /// <summary>
        /// 移动开始点
        /// </summary>
        private FCPoint m_startTouchPoint;

        /// <summary>
        /// 移动开始时的视图矩形
        /// </summary>
        private FCRect m_startRect;

        public int m_borderWidth = 2;

        /// <summary>
        /// 获取边框的宽度
        /// </summary>
        public override int getBorderWidth() {
            return m_borderWidth;
        }

        /// <summary>
        /// 设置边框的宽度
        /// </summary>
        public override void setBorderWidth(int value) {
            m_borderWidth = value;
        }

        public bool m_canResize = false;

        /// <summary>
        /// 获取是否可以调整尺寸
        /// </summary>
        public virtual bool canResize() {
            return m_canResize;
        }

        /// <summary>
        /// 设置是否可以调整尺寸
        /// </summary>
        public virtual void setCanResize(bool value) {
            m_canResize = value;
        }

        public int m_captionHeight = 20;

        /// <summary>
        /// 获取标题栏的高度
        /// </summary>
        public virtual int getCaptionHeight() {
            return m_captionHeight;
        }

        /// <summary>
        /// 设置标题栏的高度
        /// </summary>
        public virtual void setCaptionHeight(int value) {
            m_captionHeight = value;
        }

        /// <summary>
        /// 获取客户端的区域
        /// </summary>
        public virtual FCRect getClientSize() {
            int width = getWidth(), height = getHeight() - m_captionHeight;
            if (height < 0) {
                height = 0;
            }
            return new FCRect(0, m_captionHeight, width, height);
        }

        public FCWindowFrame m_frame;

        /// <summary>
        /// 获取窗体的边框
        /// </summary>
        public virtual FCWindowFrame getFrame() {
            return m_frame;
        }

        /// <summary>
        /// 设置窗体的边框
        /// </summary>
        public virtual void setFrame(FCWindowFrame value) {
            m_frame = value;
        }

        public bool m_isDialog;

        /// <summary>
        /// 获取或设置是否会话窗口
        /// </summary>
        public virtual bool isDialog() {
            return m_isDialog;
        }

        /// <summary>
        /// 设置控件的位置
        /// </summary>
        /// <param name="value"></param>
        public override void setLocation(FCPoint value)
        {
            if (m_location.x != value.x || m_location.y != value.y)
            {
                if (m_atrEx != null && m_atrEx.m_percentLocation != null)
                {
                    m_oldLocation = getLocation();
                    if (m_atrEx.m_percentLocation.x != -1)
                    {
                    }
                    else
                    {
                        m_location.x = value.x;
                    }
                    if (m_atrEx.m_percentLocation.y != -1)
                    {
                    }
                    else
                    {
                        m_location.y = value.y;
                    }
                }
                else
                {
                    m_oldLocation = m_location;
                    m_location = value;
                }
                onLocationChanged();
            }
        }

        public long m_shadowColor = FCColor.rgba(255, 255, 255, 25);

        /// <summary>
        /// 获取阴影的颜色
        /// </summary>
        public virtual long getShadowColor() {
            return m_shadowColor;
        }

        /// <summary>
        /// 设置阴影的颜色
        /// </summary>
        public virtual void setShadowColor(long value) {
            m_shadowColor = value;
        }

        public int m_shadowSize = 10;

        /// <summary>
        /// 获取阴影的大小
        /// </summary>
        public virtual int getShadowSize() {
            return m_shadowSize;
        }

        /// <summary>
        /// 设置阴影的大小
        /// </summary>
        public virtual void setShadowSize(int value) {
            m_shadowSize = value;
        }

        public bool m_useFrame = true;

        /// <summary>
        /// 是否使用框架
        /// </summary>
        /// <returns></returns>
        public bool useFrame()
        {
            return m_useFrame;
        }

        /// <summary>
        /// 设置使用框架
        /// </summary>
        /// <param name="value"></param>
        public void setUseFrame(bool value)
        {
            m_useFrame = value;
        }

        /// <summary>
        /// 将视图放到最前显示
        /// </summary>
        public override void bringToFront() {
            base.bringToFront();
            if (m_frame != null) {
                m_frame.bringToFront();
            }
        }

        /// <summary>
        /// 调用窗体关闭事件
        /// </summary>
        /// <param name="eventName">事件ID</param>
        /// <param name="cancel">是否退出</param>
        public virtual void callWindowClosingEvents(String eventName, ref bool cancel) {
            if (m_atrEx != null && m_atrEx.m_events != null && m_atrEx.m_events.containsKey(eventName))
            {
                ArrayList<Object> events = m_atrEx.m_events[eventName];
                ArrayList<Object> invokes = m_atrEx.m_invokes[eventName];
                int eventSize = events.size();
                for (int i = 0; i < eventSize; i++) {
                    FCWindowClosingEventCallBack func = events.get(i) as FCWindowClosingEventCallBack;
                    if (func != null) {
                        func.callWindowClosingEvent(eventName, this, ref cancel, invokes.get(i));
                    }
                }
            }
        }

        /// <summary>
        /// 关闭窗体
        /// </summary>
        public virtual void close() {
            bool cancel = false;
            onWindowClosing(ref cancel);
            if (!cancel) {
                if (m_frame != null) {
                    m_frame.removeView(this);
                    getNative().removeView(m_frame);
                    m_frame.delete();
                    m_frame = null;
                    setParent(null);
                } else {
                    getNative().removeView(this);
                }
                onWindowClosed();
            }
        }

        /// <summary>
        /// 销毁视图方法
        /// </summary>
        public override void delete() {
            if (!isDeleted()) {
                if (m_frame != null) {
                    m_frame.removeView(this);
                    getNative().removeView(m_frame);
                    m_frame.delete();
                    m_frame = null;
                }
            }
            base.delete();
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns></returns>
        public override String getViewType() {
            return "Window";
        }

        /// <summary>
        /// 获取动态绘图区域
        /// </summary>
        /// <returns>区域</returns>
        public FCRect getDynamicPaintRect() {
            FCSize oldSize = m_oldSize;
            if (oldSize.cx == 0 && oldSize.cy == 0) {
                oldSize = getSize();
            }
            FCRect oldRect = new FCRect(m_oldLocation.x, m_oldLocation.y, m_oldLocation.x + oldSize.cx, m_oldLocation.y + oldSize.cy);
            FCRect rect = new FCRect(m_location.x, m_location.y, m_location.x + getWidth(), m_location.y + getHeight());
            FCRect paintRect = new FCRect(Math.Min(oldRect.left, rect.left) - m_shadowSize - 10,
            Math.Min(oldRect.top, rect.top) - m_shadowSize - 10,
            Math.Max(oldRect.right, rect.right) + m_shadowSize + 10,
            Math.Max(oldRect.bottom, rect.bottom) + m_shadowSize + 10);
            return paintRect;
        }

        /// <summary>
        /// 获取事件名称列表
        /// </summary>
        /// <returns>名称列表</returns>
        public override ArrayList<String> getEventNames() {
            ArrayList<String> eventNames = base.getEventNames();
            eventNames.AddRange(new String[] { "WindowClosed", "WindowClosing" });
            return eventNames;
        }

        /// <summary>
        /// 获取属性值
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        /// <param name="type">类型</param>
        public override void getAttribute(String name, ref String value, ref String type) {
            switch (name)
            {
                case "borderwidth":
                    type = "int";
                    value = FCTran.intToStr(getBorderWidth());
                    break;
                case "canresize":
                    type = "bool";
                    value = FCTran.boolToStr(canResize());
                    break;
                case "captionheight":
                    type = "int";
                    value = FCTran.intToStr(getCaptionHeight());
                    break;
                case "shadowcolor":
                    type = "color";
                    value = FCTran.colorToStr(getShadowColor());
                    break;
                case "shadowsize":
                    type = "int";
                    value = FCTran.intToStr(getShadowSize());
                    break;
                case "useframe":
                    type = "bool";
                    value = FCTran.boolToStr(useFrame());
                    break;
                default:
                    base.getAttribute(name, ref value, ref type);
                    break;
            }
        }

        /// <summary>
        /// 获取属性列表
        /// </summary>
        /// <returns>属性列表</returns>
        public override ArrayList<String> getAttributeNames() {
            ArrayList<String> attributeNames = base.getAttributeNames();
            attributeNames.AddRange(new String[] { "BorderWidth", "CanResize", "CaptionHeight", "ShadowColor", "ShadowSize", "UseFrame" });
            return attributeNames;
        }

        /// <summary>
        /// 获取触摸状态
        /// </summary>
        /// <param name="state">状态值</param>
        /// <returns>触摸状态</returns>
        public FCCursors getResizeCursor(int state) {
            switch (state) {
                case 0:
                    return FCCursors.SizeNWSE;
                case 1:
                    return FCCursors.SizeNESW;
                case 2:
                    return FCCursors.SizeNESW;
                case 3:
                    return FCCursors.SizeNWSE;
                case 4:
                    return FCCursors.SizeWE;
                case 5:
                    return FCCursors.SizeNS;
                case 6:
                    return FCCursors.SizeWE;
                case 7:
                    return FCCursors.SizeNS;
                default:
                    return FCCursors.Arrow;
            }
        }

        /// <summary>
        /// 获取调整尺寸的点
        /// </summary>
        /// <returns>矩形集合</returns>
        public FCRect[] getResizePoints() {
            int width = getWidth(), height = getHeight();
            FCRect[] points = new FCRect[8];
            //左上
            points[0] = new FCRect(0, 0, m_borderWidth * 2, m_borderWidth * 2);
            //左下
            points[1] = new FCRect(0, height - m_borderWidth * 2, m_borderWidth * 2, height);
            //右上
            points[2] = new FCRect(width - m_borderWidth * 2, 0, width, m_borderWidth * 2);
            //右下
            points[3] = new FCRect(width - m_borderWidth * 2, height - m_borderWidth * 2, width, height);
            //左
            points[4] = new FCRect(0, 0, m_borderWidth, height);
            //上
            points[5] = new FCRect(0, 0, width, m_borderWidth);
            //右
            points[6] = new FCRect(width - m_borderWidth, 0, width, height);
            //下
            points[7] = new FCRect(0, height - m_borderWidth, width, height);
            return points;
        }

        /// <summary>
        /// 获取调整尺寸的状态
        /// </summary>
        /// <returns>状态</returns>
        public int getResizeState() {
            FCPoint mp = getTouchPoint();
            FCRect[] pRects = getResizePoints();
            int rsize = pRects.Length;
            for (int i = 0; i < rsize; i++) {
                FCRect rect = pRects[i];
                if (mp.x >= rect.left && mp.x <= rect.right
                    && mp.y >= rect.top && mp.y <= rect.bottom) {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>
        /// 滚动开始方法
        /// </summary>
        /// <returns>是否已处理</returns>
        public override bool onDragBegin() {
            FCPoint mp = getTouchPoint();
            int width = getWidth(), height = getHeight();
            if (mp.y > m_captionHeight) {
                return false;
            }
            if (m_resizePoint != -1) {
                return false;
            }
            return base.onDragBegin();
        }

        /// <summary>
        /// 拖动准备方法
        /// </summary>
        /// <param name="startOffset">可以拖动的偏移坐标量</param>
        public override void onDragReady(ref FCPoint startOffset) {
            startOffset.x = 0;
            startOffset.y = 0;
        }

        /// <summary>
        /// 触摸按下方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchDown(FCTouchInfo touchInfo) {
            base.onTouchDown(touchInfo);
            //选中点
            if (touchInfo.m_firstTouch && touchInfo.m_clicks == 1) {
                if (m_canResize) {
                    m_resizePoint = getResizeState();
                    setCursor(getResizeCursor(m_resizePoint));
                    m_startTouchPoint = getNative().getTouchPoint();
                    m_startRect = getBounds();
                }
            }
            invalidate();
        }

        /// <summary>
        /// 触摸移动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchMove(FCTouchInfo touchInfo) {
            base.onTouchMove(touchInfo);
            if (m_canResize) {
                FCPoint nowPoint = getNative().getTouchPoint();
                if (m_resizePoint != -1) {
                    int left = m_startRect.left, top = m_startRect.top, right = m_startRect.right, bottom = m_startRect.bottom;
                    windowResize(m_resizePoint, ref left, ref top, ref right, ref bottom, ref nowPoint, ref m_startTouchPoint);
                    FCRect bounds = new FCRect(left, top, right, bottom);
                    setBounds(bounds);
                    getNative().invalidate();
                } else {
                    setCursor(getResizeCursor(getResizeState()));
                }
            }
        }

        /// <summary>
        /// 触摸抬起方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchUp(FCTouchInfo touchInfo) {
            base.onTouchUp(touchInfo);
            m_resizePoint = -1;
            invalidate();
        }

        /// <summary>
        /// 绘制前景方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaintForeground(FCPaint paint, FCRect clipRect) {
            String text = getText();
            if (text != null && text.Length > 0) {
                int width = getWidth();
                FCFont font = getFont();
                FCSize tSize = paint.textSize(text, font, -1);
                FCPoint strPoint = new FCPoint();
                strPoint.x = 5;
                strPoint.y = (m_captionHeight - tSize.cy) / 2;
                FCRect tRect = new FCRect(strPoint.x, strPoint.y, strPoint.x + tSize.cx, strPoint.y + tSize.cy);
                paint.drawText(text, getPaintingTextColor(), font, tRect, -1);
            }
        }

        /// <summary>
        /// 可见状态改变方法
        /// </summary>
        public override void onVisibleChanged() {
            base.onVisibleChanged();
            if (m_useFrame)
            {
                FCNative native = getNative();
                if (native != null)
                {
                    if (isVisible())
                    {
                        if (m_frame == null)
                        {
                            m_frame = new FCWindowFrame();
                        }
                        native.removeView(this);
                        native.addView(m_frame);
                        m_frame.setSize(native.getSize());
                        if (!m_frame.containsView(this))
                        {
                            m_frame.addView(this);
                        }
                    }
                    else
                    {
                        if (m_frame != null)
                        {
                            m_frame.removeView(this);
                            native.removeView(m_frame);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 窗体正在关闭时触发
        /// </summary>
        /// <param name="cancel">是否退出</param>
        public virtual void onWindowClosing(ref bool cancel) {
            callWindowClosingEvents("onwindowclosing", ref cancel);
        }

        /// <summary>
        /// 窗体关闭时触发
        /// </summary>
        public virtual void onWindowClosed() {
            callEvents("onwindowclosed");
        }

        /// <summary>
        /// 将视图放到最下面显示
        /// </summary>
        public override void sendToBack() {
            base.sendToBack();
            if (m_frame != null) {
                m_frame.sendToBack();
            }
        }

        /// <summary>
        /// 设置属性
        /// </summary>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        public override void setAttribute(String name, String value)
        {
            switch (name)
            {
                case "borderwidth":
                    setBorderWidth(FCTran.strToInt(value));
                    break;
                case "canresize":
                    setCanResize(FCTran.strToBool(value));
                    break;
                case "captionheight":
                    setCaptionHeight(FCTran.strToInt(value));
                    break;
                case "shadowcolor":
                    setShadowColor(FCTran.strToColor(value));
                    break;
                case "shadowsize":
                    setShadowSize(FCTran.strToInt(value));
                    break;
                case "useframe":
                    setUseFrame(FCTran.strToBool(value));
                    break;
                default:
                    base.setAttribute(name, value);
                    break;
            }
        }

        /// <summary>
        /// 以会话方式显示
        /// </summary>
        public virtual void showDialog() {
            m_isDialog = true;
            show();
        }

        /// <summary>
        /// 窗体尺寸改变
        /// </summary>
        public virtual void windowResize(int resizePoint, ref int left, ref int top, ref int right, ref int bottom, ref FCPoint nowPoint, ref FCPoint startTouchPoint) {
            switch (resizePoint) {
                case 0:
                    left = left + nowPoint.x - startTouchPoint.x;
                    top = top + nowPoint.y - startTouchPoint.y;
                    break;
                case 1:
                    left = left + nowPoint.x - startTouchPoint.x;
                    bottom = bottom + nowPoint.y - startTouchPoint.y;
                    break;
                case 2:
                    right = right + nowPoint.x - startTouchPoint.x;
                    top = top + nowPoint.y - startTouchPoint.y;
                    break;
                case 3:
                    right = right + nowPoint.x - startTouchPoint.x;
                    bottom = bottom + nowPoint.y - startTouchPoint.y;
                    break;
                case 4:
                    left = left + nowPoint.x - startTouchPoint.x;
                    break;
                case 5:
                    top = top + nowPoint.y - startTouchPoint.y;
                    break;
                case 6:
                    right = right + nowPoint.x - startTouchPoint.x;
                    break;
                case 7:
                    bottom = bottom + nowPoint.y - startTouchPoint.y;
                    break;
            }
        }

        /// <summary>
        /// 更新界面
        /// </summary>
        public override void update()
        {
            if (m_native != null)
            {
                base.update();
                m_oldLocation = getLocation();
            }
        }
    }
}
